#ifndef CV_MATH_VECTOR_H
#define CV_MATH_VECTOR_H

#include <cmath>

/**	 Cool VES Math */
namespace cvMath
{
	// General vector class template.
	template<typename T> class Vec2
	{
		public:
			// public data members
			T x, y;

			//ctors
			Vec2<T>();
			Vec2<T>(const T i, const T j);
			template<typename J> Vec2<T>(const Vec2<J> &copy);	// allow conversion from any other Vec2 type.
			Vec2<T>& operator=	(const Vec2<T> &copy);
	};

	// Operators
	template<typename T> Vec2<T> operator-	(const Vec2<T> &leftVec);
	template<typename T> Vec2<T> operator+	(const Vec2<T> &leftVec, const Vec2<T> &rightVec);
	template<typename T> Vec2<T> operator-	(const Vec2<T> &leftVec, const Vec2<T> &rightVec);
	template<typename T> Vec2<T> operator*	(const Vec2<T> &leftVec, const T realVal);
	template<typename T> Vec2<T> operator/	(const Vec2<T> &leftVec, const T realVal);
	// linear multiply and divide by vector! vector components are multipled or divided)
	template<typename T> Vec2<T> operator*	(const Vec2<T> &leftVec, const Vec2<T> &rightVec);
	template<typename T> Vec2<T> operator/	(const Vec2<T> &leftVec, const Vec2<T> &rightVec);

	// Assingment operators
	template<typename T> Vec2<T>& operator+=	(Vec2<T> &leftVec, const Vec2<T> &rightVec);
	template<typename T> Vec2<T>& operator-=	(Vec2<T> &leftVec, const Vec2<T> &rightVec);
	template<typename T> Vec2<T>& operator*=	(Vec2<T> &leftVec, const T realVal);
	template<typename T> Vec2<T>& operator/=	(Vec2<T> &leftVec, const T realVal);
	template<typename T> Vec2<T>& operator*=	(Vec2<T> &leftVec, const Vec2<T> &rightVec);
	template<typename T> Vec2<T>& operator/=	(Vec2<T> &leftVec, const Vec2<T> &rightVec);

	// Comparison. (vectors must not cross, and their lenght must be same)
	template<typename T> bool equals(const Vec2<T> &leftVec, const Vec2<T> &rightVec, const T threshold = 0.0);

	// Other operations.
	template<typename T> Vec2<T>& normalize(const Vec2<T> &leftVec);
	template<typename T> Vec2<T> complexMultiply(const Vec2<T> &leftVec, const Vec2<T> &rightVec);
	// products..
	template<typename T> T dot(const Vec2<T> &leftVec, const Vec2<T> &rightVec);
	template<typename T> T cross(const Vec2<T> &leftVec, const Vec2<T> &rightVec);
	// lenght..
	template<typename T> T length(const Vec2<T> &leftVec);
	template<typename T> T lengthSq(const Vec2<T> &leftVec);

	// projections..
	template<typename T> T scalarProjection(const Vec2<T> &leftVec, const Vec2<T> &rightVec);
	template<typename T> Vec2<T> vectorProjection(const Vec2<T> &leftVec, const Vec2<T> &rightVec);

	// normals..
	template<typename T> Vec2<T> normalRight(const Vec2<T> &leftVec);
	template<typename T> Vec2<T> normalLeft(const Vec2<T> &leftVec);

	// conversion to integer type from floating point.
	template<typename T> Vec2<int> round(const Vec2<T> &leftVec);
	template<typename T> Vec2<int> rounddown(const Vec2<T> &leftVec);
	template<typename T> Vec2<int> roundup(const Vec2<T> &leftVec);

	// distance beetween two vectors
	template<typename T> T distance(const Vec2<T> &leftVec, const Vec2<T> &rightVec);

	// [0, 90] degree vector angle beetween two vectors
	template<typename T> T vectorAngle(const Vec2<T> &leftVec, const Vec2<T> &rightVec);

	// [0, 360[ degree angle beetween anchor left and pointing right.
	template<typename T> T getAngle(const Vec2<T> &leftVec, const Vec2<T> &rightVec);

/// TEMPLATE IMPLEMENTATION...
#include "../../impl/Math/Vector.inl"

	// Common vector types
	typedef Vec2<float> Vec2f;
	typedef Vec2<double> Vec2d;
	typedef Vec2<int>	Vec2i;

}; // end of namespace cvMath

#endif // end of CV_MATH_VECTOR_HPP
